package com.zxb.core.dao;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.zxb.core.common.User;
import com.zxb.core.common.Req;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;

/**
 * @author Zxb
 */
@Component
public class BaseEntityHandler implements MetaObjectHandler {
    public static final String CREATE_TIME = "createTime";
    public static final String UPDATE_TIME = "updateTime";
    public static final String CREATE_BY = "createBy";
    public static final String UPDATE_BY = "updateBy";
    public static final String IS_DEL = "isDel";
    public static final String VER = "ver";

    private static final String DEFAULT_BY = "system";

    private final ThreadLocal<Timestamp> now = new ThreadLocal<>();
    private final ThreadLocal<String> username = new ThreadLocal<>();

    private Timestamp getNow() {
        Timestamp t = now.get();
        if (t == null) {
            t = new Timestamp(System.currentTimeMillis());
            now.set(t);
        }
        return t;
    }

    private String getCurrUsername() {
        String s = username.get();
        if (s == null) {
            User u = Req.getCurrUser();
            s = u == null ? DEFAULT_BY : u.getUsername();
            username.set(s);
        }
        return s;
    }

    private void clearThreadLocal() {
        now.remove();
        username.remove();
    }

    @Override
    public void insertFill(MetaObject metaObject) {
        if (metaObject.hasSetter(CREATE_TIME)) {
            this.strictInsertFill(metaObject, CREATE_TIME, Timestamp.class, getNow());
        }
        if (metaObject.hasSetter(CREATE_BY)) {
            this.strictInsertFill(metaObject, CREATE_BY, String.class, getCurrUsername());
        }
        if (metaObject.hasSetter(UPDATE_TIME)) {
            this.strictInsertFill(metaObject, UPDATE_TIME, Timestamp.class, getNow());
        }
        if (metaObject.hasSetter(UPDATE_BY)) {
            this.strictInsertFill(metaObject, UPDATE_BY, String.class, getCurrUsername());
        }
        if (metaObject.hasSetter(IS_DEL)) {
            this.strictInsertFill(metaObject, IS_DEL, Boolean.class, false);
        }
        if (metaObject.hasSetter(VER)) {
            this.strictInsertFill(metaObject, VER, Integer.class, 0);
        }
        clearThreadLocal();
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        if (metaObject.hasSetter(UPDATE_TIME)) {
            this.strictUpdateFill(metaObject, UPDATE_TIME, Timestamp.class, getNow());
        }
        if (metaObject.hasSetter(UPDATE_BY)) {
            this.strictUpdateFill(metaObject, UPDATE_BY, String.class, getCurrUsername());
        }
        clearThreadLocal();
    }
}
